using System;
using System.Drawing;
using System.Collections;
using System.Windows.Forms;

namespace SuDokuSolution
{
	/// <summary>
	/// The graphicsl cell to be drawn on the screen, containing cell
	/// data and mouse events
	/// </summary>
	public class GraphicalCell
	{		

		/// <summary>
		/// Cell Data
		/// </summary>
        public CellData cellData;
        
		/// <summary>
		/// Reference to the parent grid of the  cell
		/// </summary>
		private GridControl parentGrid;

		/// <summary>
		/// The nbs is marked by user as candidate nb
		/// </summary>
		public ArrayList CheckedNbs;		

		/// <summary>
		/// whether to redraw the cell or not
		/// </summary>
		public bool redraw=true;

		/// <summary>
		/// size of the cell
		/// </summary>
		public Size cellSize;

		/// <summary>
		/// size of the sub cell
		/// </summary>
		public Size subCellSize;

		/// <summary>
		/// lacation of the cell
		/// </summary>
		public Point cellLocation;

		/// <summary>
		/// rectangle to store the drawing area of the cell
		/// </summary>
		public Rectangle cellRect;

		/// <summary>
		/// background brush to be used
		/// </summary>
		private Brush backGroundBrush;

		/// <summary>
		/// flag to draw a nb in error color if an invalid no has been selected
		/// </summary>
		public bool MarkError=false;

		/// <summary>
		/// costructor
		/// </summary>
		/// <param name="gc">parent grid</param>
		/// <param name="b">BackGround Brush</param>
		public GraphicalCell(GridControl gc,Brush b)
		{
			this.parentGrid=gc;
			this.backGroundBrush=b;
			this.CheckedNbs=new ArrayList(Constants.nbOfCells);
			this.cellData=new CellData();
		}

		
		/// <summary>
		/// Method to paint a cell
		/// </summary>
		/// <param name="graphics">Graphics reference</param>
		public void Paint(Graphics graphics)		
		{
			//fill background
			graphics.FillRectangle(backGroundBrush,cellRect);

			if(!redraw)
				return;

			Brush selBrush;
			if(cellData.problemNb==Constants.NoNumber)
			{
				//draw vertical lines
				for(int i=1;i<Constants.nbOfLines;i++)
				{
					graphics.DrawLine(DrawingTools.LightPen,
						cellLocation.X+subCellSize.Width*i,cellLocation.Y+1,
						cellLocation.X+subCellSize.Width*i,cellLocation.Y+cellSize.Height-1);
				}

				//draw horizontal lines
				for(int i=1;i<Constants.nbOfLines;i++)
				{
					graphics.DrawLine(DrawingTools.LightPen,
						cellLocation.X+1,cellLocation.Y+subCellSize.Height*i,
						cellLocation.X+cellSize.Width-1,cellLocation.Y+subCellSize.Height*i);
				}

				//draw marked nbs
				foreach(Object ob in this.CheckedNbs)
				{
					int nb=(int)ob;				
					if(this.cellData.candidateNb.Contains(nb) || !parentGrid.simultaneousCheck)            //if valid nb
						selBrush=DrawingTools.AnswerBrush;
					else
						selBrush=DrawingTools.ErrorBrush;
				
					SizeF fontSize=graphics.MeasureString(nb.ToString(),DrawingTools.miniSelectedFont);
					graphics.DrawString(nb--.ToString(),DrawingTools.miniSelectedFont,
						selBrush,cellLocation.X+subCellSize.Width*(nb%Constants.nbOfLines)+(subCellSize.Width-fontSize.Width)/2,
						cellLocation.Y+subCellSize.Height*(nb/Constants.nbOfLines)+(subCellSize.Height-fontSize.Height)/2);
				}
			}

			else
			{
				
				if(cellData.readOnly)
					selBrush=DrawingTools.ProblemBrush;
				else if(!MarkError || !parentGrid.simultaneousCheck )
                    selBrush=DrawingTools.AnswerBrush;
				else
					selBrush=DrawingTools.ErrorBrush;
                
				SizeF fontSize=graphics.MeasureString(cellData.problemNb.ToString(),DrawingTools.SelectedFont);

				graphics.DrawString(cellData.problemNb.ToString(),DrawingTools.SelectedFont,
					selBrush,cellLocation.X+(cellSize.Width-fontSize.Width)/2,
					cellLocation.Y+(cellSize.Height-fontSize.Height)/2);
			}
		}

		/// <summary>
		/// processes the mouse single click event 
		/// </summary>
		/// <param name="e">mouse event args</param>		
		public void MouseDown(MouseEventArgs e)
		{	
			if(cellData.readOnly)
				return;
			
			int clickedNb=getClickedNb(e.X-cellLocation.X,e.Y-cellLocation.Y);
			if(cellData.problemNb==Constants.NoNumber)
			{
				if(CheckedNbs.Contains(clickedNb))
					CheckedNbs.Remove(clickedNb);
				else
					CheckedNbs.Add(clickedNb);
			}
			else{} //do nothing
			parentGrid.RedrawCell(this);
		}

        /// <summary>
        /// Processes Mouse double click event 
        /// </summary>
        /// <param name="e">MouseEventArgs</param>        
		public void DoubleClick(MouseEventArgs e)
		{
			if(cellData.readOnly)
				return ;
			int clickedNb=getClickedNb(e.X-cellLocation.X,e.Y-cellLocation.Y);
			
			if(cellData.problemNb==Constants.NoNumber)
				cellData.problemNb=clickedNb;
			else
				cellData.problemNb=Constants.NoNumber;

			CheckedNbs.Clear();  //clear the marked nbs			
		}

        /// <summary>
        /// return the nb clicked in a cell
        /// </summary>
        /// <param name="x">the x position wrt cell</param>
        /// <param name="y">the y pos wrt cell</param>
        /// <returns>the clicked nb </returns>
        public int getClickedNb(int x,int y)
		{
			int col=(int)(x/subCellSize.Width);
			int row=(int)(y/subCellSize.Height);

			int nb=row*Constants.nbOfLines+col+1;            			
			
			return nb;
		}
	}
}
